20. 常用图形绘制

本章概要

  • 学习材料:有来源、单位和年份的省级指标表。
  • 本章任务:运行 lst-gdp-data-prepfig-gdp-with-labels,整理排序并绘制带数值标签的比较图。
  • 完成后你将得到:排序表、单轴图、标签与来源口径说明。
  • 自我检查:核对图上标签与数据表逐项一致;来源/单位/年份缺失时先检查原因。
  • 拓展练习:把选图与标签规则拓展应用到另一长三角指标。

本章学习目标

  • 掌握柱状图与条形图的绘制方法
  • 学会为图表添加数值标签
  • 识别双轴图的风险与可选应用场景
  • 根据数据类型选择合适的图表

选择合适的图表

不同数据类型需要不同的图表:

数据类型 推荐图表 说明
时间序列 折线图 展示趋势
分类比较 柱状图/条形图 比较大小
相关性 散点图 观察关系
占比 饼图 显示份额
分布 直方图/箱线图 显示分布

运行前预测|中国GDP省份排名TOP5

  • 输入预测:运行前先写出 GDP 的业务含义、数据类型或取值范围,并判断哪一个输入最可能改变结果。
  • 结果预测:不展开答案,先预测将得到GDP 的结果;同时写出方向、数量级或表格/图形结构。
  • 完成要求:能独立说明本任务从输入到“中国GDP省份排名TOP5”结果的关键步骤,原样录入平台代码并得到可核对的运行结果。

⭐ 中国GDP省份排名TOP5

展开完整代码(投影默认折叠)
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
# 导入模块
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei'] #用黑体显示中文

# 构建数据
GDP = [129118.6,122875.6,87435.1,77715.4,61345.1]

# 绘图
plt.bar(range(5),GDP,align = "center",color = "steelblue",alpha = 0.6)
# 添加y轴标签
plt.ylabel("GDP:亿元人民币")
# 设置Y轴的刻度范围
plt.ylim([40000,150000])
# 添加x轴刻度标签
plt.xticks(range(5),['广东省','江苏省','山东省','浙江省','河南省'])
# 添加标题
plt.title('2022年中国GDP排名前5的省份')
# 为每个条形图添加数值标签
for x,y in enumerate(GDP):
  plt.text(x,y+300,s=y,ha='center')  # 添加文本标注
# 保存图形
plt.savefig("1.png")
plt.show()  # 显示图形

任务复盘|中国GDP省份排名TOP5

依据边界:平台固定数值缺少来源快照、统计公报版本和核对日期,只能作为柱状图语法示例数据;不得据此发布“2022年排名”或全国占比。

拓展练习:把数据替换为一个中国企业或市场序列,改变一个分组或时间窗口;说明图形结论是否改变,以及为何。

柱状图 vs 条形图:何时使用?

  • 柱状图(垂直):适合类别名称短、强调数值高度差异
  • 条形图(水平):适合类别名称长、便于阅读标签
  • 两者本质相同,只是方向不同

准备数据:构建DataFrame

Listing 1
展开实现代码
import matplotlib.pyplot as plt
import pandas as pd

# 平台固定绘图示例数据(单位标签为亿元,但不作为2022年统计事实)
data = {
    '省份': ['广东', '江苏', '山东', '浙江', '河南'],
    'GDP': [129118, 122875, 87435, 77715, 61345]
}
df = pd.DataFrame(data)

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['Source Han Serif SC']
plt.rcParams['axes.unicode_minus'] = False

print(df)
   省份     GDP
0  广东  129118
1  江苏  122875
2  山东   87435
3  浙江   77715
4  河南   61345

绘制柱状图与条形图

展开实现代码
fig, axes = plt.subplots(1, 2, figsize=(12, 4.5))

# 子图1:纵向柱状图
axes[0].bar(df['省份'], df['GDP'], color='steelblue', edgecolor='black')
axes[0].set_title('中国GDP排名TOP5(柱状图)', fontsize=16)
axes[0].set_xlabel('省份', fontsize=16)
axes[0].set_ylabel('GDP(亿元)', fontsize=16)
axes[0].grid(axis='y', alpha=0.3)

# 子图2:横向条形图
axes[1].barh(df['省份'], df['GDP'], color='coral', edgecolor='black')
axes[1].set_title('中国GDP排名TOP5(条形图)', fontsize=16)
axes[1].set_xlabel('GDP(亿元)', fontsize=16)
axes[1].grid(axis='x', alpha=0.3)

plt.tight_layout()
plt.show()
图中展示中国GDP排名TOP5:柱状图与条形图对比;读者应依据坐标、图例与注释比较主要模式。
Figure 1: 中国GDP排名TOP5:柱状图与条形图对比

为图表添加数值标签

数值标签让读者无需对照坐标轴即可读取精确值:

展开实现代码
fig, axes = plt.subplots(1, 2, figsize=(12, 3.7))

# 柱状图 + 数值标签
axes[0].bar(df['省份'], df['GDP'], color='steelblue', edgecolor='black')
axes[0].set_title('柱状图:数值标签在顶部', fontsize=16)
axes[0].set_ylabel('GDP(亿元)', fontsize=16)
for i, v in enumerate(df['GDP']):
    axes[0].text(i, v + 2000, f'{v:,}', ha='center', fontsize=16)

# 条形图 + 数值标签
axes[1].barh(df['省份'], df['GDP'], color='coral', edgecolor='black')
axes[1].set_title('条形图:数值标签在右侧', fontsize=16)
axes[1].set_xlabel('GDP(亿元)', fontsize=16)
for i, v in enumerate(df['GDP']):
    axes[1].text(v + 2000, i, f'{v:,}', va='center', fontsize=16)

plt.tight_layout()
plt.show()
图中展示带数值标签的柱状图与条形图;读者应依据坐标、图例与注释比较主要模式。
Figure 2: 带数值标签的柱状图与条形图

数值标签的关键参数

  • plt.text(x, y, s, ha, va, fontsize) 用于添加文本
  • 柱状图x 为柱子索引,y 为柱顶上方偏移
  • 条形图x 为条形右端偏移,y 为条形索引
  • ha='center':水平居中对齐
  • va='center':垂直居中对齐
  • f'{v:,}':千位分隔符格式化数值

绘图示例数据的组内统计

Listing 2
展开实现代码
# 五省GDP总和
total_gdp = df['GDP'].sum()

# 各省占比
gdp_share = df['GDP'] / total_gdp * 100

print('详细数据:')
for _, row in df.iterrows():
    print(f"  {row['省份']}: {row['GDP']:,}亿元")

print(f'\n五省GDP总计: {total_gdp:,}亿元')
print('未绑定权威全国总量:停止计算全国占比')
详细数据:
  广东: 129,118亿元
  江苏: 122,875亿元
  山东: 87,435亿元
  浙江: 77,715亿元
  河南: 61,345亿元

五省GDP总计: 478,488亿元
未绑定权威全国总量:停止计算全国占比

可选扩展|双轴图的应用场景

本章核心检查使用单轴图完成趋势、类别与关系表达。双轴图仅供已有单轴依据后选修;若标准化单轴或并排小图足以回答问题,应优先使用它们。

当需要在同一图表中展示两个不同量纲的变量时,使用双轴图:

  • 股票价格(元)与成交量(万股)
  • 收益率(%)与波动率(%)
  • 利率通胀率

核心方法:ax1.twinx() 创建共享x轴的第二个y轴

可选扩展|绘制双轴图

展开完整代码
import numpy as np

fig = plt.figure(figsize=(12, 4.2))

# 生成示例数据
np.random.seed(42)
x = np.arange(10)
y1 = np.random.randn(10).cumsum()
y2 = np.random.randn(10).cumsum() * 100

# 左y轴:收益率(蓝色)
ax1 = fig.add_subplot(111)
ax1.plot(x, y1, 'b-', label='收益率', linewidth=2)
ax1.set_xlabel('时间', fontsize=16)
ax1.set_ylabel('收益率', fontsize=16, color='b')
ax1.tick_params(axis='y', labelcolor='b')
ax1.legend(loc='upper left')

# 右y轴:成交量(红色)
ax2 = ax1.twinx()
ax2.plot(x, y2, 'r-', label='成交量', linewidth=2)
ax2.set_ylabel('成交量', fontsize=16, color='r')
ax2.tick_params(axis='y', labelcolor='r')
ax2.legend(loc='upper right')

ax1.set_title('双轴图:收益率与成交量', fontsize=16)
plt.show()
图中展示双轴图:收益率与成交量;读者应依据坐标、图例与注释比较主要模式。
Figure 3: 双轴图:收益率与成交量

可选扩展|双轴图的关键代码解析

  • ax1 = fig.add_subplot(111):创建主坐标轴
  • ax2 = ax1.twinx():创建共享x轴的第二个y轴
  • 左轴用蓝色,右轴用红色,形成视觉区分
  • tick_params(labelcolor=...) 使刻度颜色与曲线一致

遇到问题时:双轴缩放可制造共变观感。没有同期原值表、清晰颜色映射和独立统计核对时,不发布双轴结论;双轴页不决定本章核心学习要求。

本章小结

图表类型 核心函数 适用场景
柱状图 plt.bar() 分类数值比较
条形图 plt.barh() 长标签分类比较
数值标签 plt.text() 标注精确数值
双轴图 ax.twinx() 双量纲对比

随堂练习

  • 问题 1|需要准备哪些数据?:有来源、单位和年份的省级指标表。
  • 问题 2|需要完成哪些操作?:运行 lst-gdp-data-prepfig-gdp-with-labels,整理排序并绘制带数值标签的比较图。
  • 问题 3|应得到哪些结果?:排序表、单轴图、标签与来源口径说明。
  • 问题 4|怎样确认结果可靠?:核对图上标签与数据表逐项一致;来源/单位/年份缺失时先检查原因。
  • 问题 5|换一个情境,怎样继续应用?:把选图与标签规则拓展应用到另一长三角指标。
  • 作答提示:请依次写清所用数据、分析过程、所得结果、核对方法和拓展思考。课程所需数据见前言中的下载入口;教学平台固定题按页面说明完成。

教师参考解答|答案与说明 1

  • 所用数据与字段stock/stock_basic_data.h5 中的 stock_basic_info 表;使用 order_book_id/status/type/province 字段,统计长三角四省市的在市 A 股公司数,单位为“家”,数据日期为 2026-08-31
  • 解答示例|省级排序与标签核对(平台保护块之外):

教师参考解答|代码 1

展开代码(代码区可独立滚动)
from pathlib import Path  # 导入路径工具以定位课程授权快照
import pandas as pd  # 导入表格工具以完成省级汇总
import matplotlib.pyplot as plt  # 导入绘图库以绘制单轴比较图
snapshot_path=Path('/home/ubuntu/r2_data_mount/data/stock/stock_basic_data.h5')  # 指定课程本地股票基本信息快照
if not snapshot_path.is_file(): raise FileNotFoundError('未找到课程数据文件,请从课程数据下载入口获取并核对文件位置')  # 文件缺失时提示读者重新下载
company_table=pd.read_hdf(snapshot_path,key='stock_basic_info')  # 读取已登记的真实表与key
target_provinces=['上海市','江苏省','浙江省','安徽省']  # 固定长三角四省市比较范围
active_companies=company_table.loc[(company_table['status']=='Active')&(company_table['type']=='CS')]  # 保留快照中的在市普通股公司
province_counts=active_companies.loc[active_companies['province'].isin(target_provinces)].groupby('province').size()  # 按省级标签计算公司数
province_table=province_counts.reindex(target_provinces,fill_value=0).rename('company_count').sort_values()  # 补齐范围并按指标排序
figure,comparison_axis=plt.subplots()  # 创建单轴以避免双量纲误导
bar_objects=comparison_axis.barh(province_table.index,province_table.values)  # 绘制排序后的省级比较条形图
comparison_axis.bar_label(bar_objects,labels=[f'{value}家' for value in province_table.values],padding=3)  # 让图上标签与表值逐项对应
comparison_axis.set_xlabel('在市A股公司数(家)')  # 标注指标单位
comparison_axis.set_title('长三角四省市在市A股公司数|课程快照访问日 2026-08-31')  # 标注范围与访问期而不冒充供应商更新日
assert [text.get_text() for text in comparison_axis.texts]==[f'{value}家' for value in province_table.values]  # 独立核对标签与排序表完全一致
print(province_table.to_frame(),snapshot_path.name,'访问日 2026-08-31')  # 输出来源、期间、单位与排序表依据

教师参考解答|答案与说明 2

  • 解释答案:条形图适合比较少量省级指标;先排序,再让每个“家”标签与 province_table 同序核对,来源、单位与访问期必须随图写出。
  • 拓展应用答案:换成另一项长三角省级指标,保持地区名称、计量单位、排序和图上标签一致;如果来源没有注明统计年份,应写明数据访问日期,并补充查询年份信息。
  • 参考结果:四行省级排序表、四根横条、四个“家”标签、文件/key、访问日与单位;实际数值由授权快照运行产生,不在课件中预填。
  • 边界 / 局限:访问日不是供应商数据更新日;公司数只是证券市场覆盖指标,不代表省级经济规模。
  • 常见错误:把季度公司收入示例数据当省级答案;标签未随排序重排;缺来源、单位或年份仍下结论。